/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 *
 * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
 *
 * Contributor(s): 
 *  Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
 *  
 * If you didn't download this code from the following link, you should check
 * if you aren't using an obsolete version: http://www.isqlviewer.com
 */
package org.isqlviewer.swing;

import static org.isqlviewer.UserOptions.DEF_CONSOLE_ERR_COLOR;
import static org.isqlviewer.UserOptions.DEF_CONSOLE_FG_COLOR;
import static org.isqlviewer.UserOptions.DEF_CONSOLE_FONT;
import static org.isqlviewer.UserOptions.DEF_CONSOLE_SQL_COLOR;
import static org.isqlviewer.UserOptions.DEF_CONSOLE_TIME_FMT;
import static org.isqlviewer.UserOptions.KEY_CONSOLE_ERR_COLOR;
import static org.isqlviewer.UserOptions.KEY_CONSOLE_FG_COLOR;
import static org.isqlviewer.UserOptions.KEY_CONSOLE_FONT;
import static org.isqlviewer.UserOptions.KEY_CONSOLE_SQL_COLOR;
import static org.isqlviewer.UserOptions.KEY_CONSOLE_TIME_FMT;

import java.awt.Color;
import java.awt.Font;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import java.util.prefs.Preferences;

import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import org.isqlviewer.util.IsqlToolkit;
import org.isqlviewer.util.StringUtilities;

/**
 * @author Mark A. Kobold &lt;mkobold at isqlviewer dot com&gt;
 * @version 1.0
 */
public class DocumentAppender extends AppenderSkeleton implements PreferenceChangeListener {

    private Document document = null;
    private JTextComponent view = null;
    private SimpleDateFormat sdf = new SimpleDateFormat("");
    private Preferences preferences = Preferences.userRoot().node(IsqlToolkit.getRootPreferencesNode());

    public DocumentAppender(Document document, JTextComponent view) {

        super();
        this.document = document;
        this.view = view;
        sdf.applyPattern(preferences.get(KEY_CONSOLE_TIME_FMT, DEF_CONSOLE_TIME_FMT));
        String fontString = preferences.get(KEY_CONSOLE_FONT, DEF_CONSOLE_FONT);
        view.setFont(StringUtilities.parseFontString(fontString));
    }

    @Override
    protected void append(LoggingEvent event) {

        SimpleAttributeSet sas = new SimpleAttributeSet();
        Font font = view.getFont();
        StyleConstants.setFontFamily(sas, font.getFamily());
        StyleConstants.setFontSize(sas, font.getSize());
        StyleConstants.setBold(sas, font.isBold());
        StyleConstants.setItalic(sas, font.isItalic());
        StyleConstants.setBackground(sas, view.getBackground());

        int last = document.getLength();
        try {
            Color color = null;
            Level level = event.getLevel();
            switch (level.toInt()) {
                case Level.DEBUG_INT :
                case Level.WARN_INT :
                    color = Color.decode(preferences.get(KEY_CONSOLE_SQL_COLOR, DEF_CONSOLE_SQL_COLOR));
                    break;
                case Level.FATAL_INT :
                case Level.ERROR_INT :
                    color = Color.decode(preferences.get(KEY_CONSOLE_ERR_COLOR, DEF_CONSOLE_ERR_COLOR));
                    break;
                default :
                    color = Color.decode(preferences.get(KEY_CONSOLE_FG_COLOR, DEF_CONSOLE_FG_COLOR));
                    break;
            }
            StyleConstants.setForeground(sas, color);
            document.insertString(last, format(event), sas);
            document.insertString(last, "\n", null);
            last = document.getLength();
        } catch (BadLocationException ignored) {

        } finally {
            view.setCaretPosition(last);
        }
    }

    public void close() {

    }

    public boolean requiresLayout() {

        return false;
    }

    public void preferenceChange(PreferenceChangeEvent event) {

        if (event == null)
            return;

        String key = event.getKey();
        String val = event.getNewValue();

        if (key.equals(KEY_CONSOLE_TIME_FMT)) {
            sdf.applyPattern(val);
        }
    }

    private String format(LoggingEvent event) {

        StringBuilder builder = new StringBuilder(32);

        builder.append(sdf.format(new Date(event.timeStamp)));
        builder.append(' ');
        builder.append(event.getRenderedMessage());

        ThrowableInformation errors = event.getThrowableInformation();
        if (errors != null) {
            String[] stackTrace = errors.getThrowableStrRep();
            for (int i = 0; i < stackTrace.length; i++) {
                builder.append('\n');
                builder.append('\t');
                builder.append(stackTrace[i].trim());
            }
        }
        return builder.toString();
    }
}